#ifdef _MSC_VER
#include <crtdbg.h>
#endif
#include "sock.h"

in_addr_t inet_addr_ex(const char* host)
{
    struct in_addr result;
    result.s_addr = inet_addr(host);
    if (result.s_addr == INADDR_NONE) {
        struct hostent* ht = 0;
        if ((ht = gethostbyname(host)) != 0) {
            result = *((struct in_addr*)ht->h_addr);
        }
    }
#ifdef _MSC_VER
    return result.s_addr;
#elif __GNUC__
    return result.s_addr;
#endif
}

int sock_setnblock(SOCKET fd, int act) {
#ifdef WIN32
    unsigned int arg = (act ? 1 : 0);
    return ioctlsocket(fd, FIONBIO, &arg);
#else
    int flags = fcntl(fd, F_GETFL, 0);
    if (flags < 0)  {
        return -1;
    }
    if (act){
        if (flags & O_NONBLOCK)
            ;
        else {
            return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
        }
    }
    else {
        if (flags & O_NONBLOCK) {
            flags &= ~O_NONBLOCK;
            return fcntl(fd, F_SETFL, flags);
        }           
    }
    return 0;

#endif
}

int sock_setndelay(SOCKET fd, int act) {
#ifndef TCP_NODELAY
    #define TCP_NODELAY 0x0001
#endif
    int bNoDelay = act;
    return (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
                     (char *) &bNoDelay, sizeof(bNoDelay)));
}

int sock_setlinger(SOCKET fd, u_short l_onoff, u_short l_linger)
{
    struct linger lin = {l_onoff, l_linger};
    return setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&lin, sizeof(lin));
}

int sock_setkeepalive(SOCKET fd, int act) 
{
    unsigned int arg = (act ? 1 : 0);
    return (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
                     (char *) &arg, sizeof(arg)));
}

int sock_create_nb(int domain, int type, int protocol)
{
    int fd = socket(domain, type, protocol);
    if (fd != -1) {
        sock_setnblock(fd, 1);
    }
    return fd;
}
